#include "BlockQueue.hpp"
#include "Task.hpp"
#include <iostream>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>

//构建两个缓冲区
struct BlockQueues
{
    BlockQueues(size_t csize = BlockQueue<CalTask>::gmaxsize, size_t ssize = BlockQueue<SaveTask>::gmaxsize)
    {
        _c_bq = new BlockQueue<CalTask>(csize);
        _s_bq = new BlockQueue<SaveTask>(ssize);
    }

    ~BlockQueues()
    {
        delete _c_bq;
        delete _s_bq;
    }
    BlockQueue<CalTask>* _c_bq;     //计算缓冲区
    BlockQueue<SaveTask>* _s_bq;    //保存缓冲区
};

void *produce(void *args)
{
    // BlockQueue<int> *bq = static_cast<BlockQueue<int> *>(args);
    BlockQueue<CalTask> *c_bq = static_cast<BlockQueues*>(args)->_c_bq;
    std::string opr = "+-*/%";

    while (true)
    {
        // int data = rand() % 10 + 1;
        // bq->push(data);
        // std::cout << "生产数据：" << data << std::endl;


        int x = rand() % 10 + 1;
        int y = rand() % 5 + 1;
        int opcode = rand() % opr.size();
        CalTask t(x, y, opr[opcode], mymath);
        c_bq->push(t);
        printf("生产计算任务：%d %c %d = ?\n",x, opr[opcode], y);
        
        sleep(1);
    }
    return nullptr;
}

void *comsume(void *args)
{
    // BlockQueue<int> *bq = static_cast<BlockQueue<int> *>(args);
    BlockQueue<CalTask> *c_bq = static_cast<BlockQueues*>(args)->_c_bq;
    BlockQueue<SaveTask> *s_bq = static_cast<BlockQueues*>(args)->_s_bq;
    
    while(true)
    {
        // int out;
        // bq->pop(&out);
        // std::cout << "消费数据：" << out << std::endl;

        //处理计算任务
        CalTask t;
        c_bq->pop(&t);
        std::string result = t();
        std::cout << "处理计算任务：" << result << std::endl;
        // sleep(1);

        //将计算好的任务发送到保存缓冲区
        SaveTask st(result,mysave);
        s_bq->push(st);
        std::cout << "推送保存任务完成..." << std::endl;

    }
    return nullptr;
}

void* save(void* args)
{
    BlockQueue<SaveTask> *s_bq = static_cast<BlockQueues*>(args)->_s_bq;

    while(true)
    {
        SaveTask st;
        s_bq->pop(&st);
        
        std::string targetpath = "./log.txt";
        st(targetpath);
        std::cout << "保存任务完成..." << std::endl;
    }

    return nullptr;
}

int main()
{
    srand((unsigned int)time(0) ^ getpid());
    // BlockQueue<int> *bq = new BlockQueue<int>();
    // BlockQueue<CalTask>* bq = new BlockQueue<CalTask>();
    BlockQueues* bqs = new BlockQueues;

    const int n = 5;
    //prodecer生产任务，comsumer处理任务，saver保存comsumer处理后的任务
    pthread_t producer[n], comsumer, saver;
    for(int i = 0; i < n; i++)
    {
        pthread_create(producer + i, nullptr, produce, (void *)bqs);
    }
    pthread_create(&comsumer, nullptr, comsume, (void *)bqs);
    pthread_create(&saver,nullptr,save,(void*)bqs);

    for(int i = 0; i < n; i++)
    {
        pthread_join(producer[i], nullptr);
    }
    pthread_join(comsumer, nullptr);
    delete bqs;
    return 0;
}